package com.wngbms;

import com.google.common.util.concurrent.*;
import lombok.extern.slf4j.Slf4j;

import javax.annotation.Nullable;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

@Slf4j
public class DrinkTeaDemo {

    public static void main(String[] args) {
        DrinkJob job = new DrinkJob();

        ExecutorService pool = Executors.newFixedThreadPool(5);
        ListeningExecutorService gPool = MoreExecutors.listeningDecorator(pool);

        // 烧水, 带泛型的Future
        ListenableFuture<Boolean> future = gPool.submit(new HotWaterJob());
        Futures.addCallback(future, new FutureCallback<Boolean>() {
            @Override
            public void onSuccess(@Nullable Boolean aBoolean) {
                job.waterOk = true;
                job.drinkTea();
            }

            @Override
            public void onFailure(Throwable throwable) {
                log.error("hot water failed", throwable);
            }
        }, gPool);

        // 洗茶杯
        ListenableFuture<Boolean> future1 = gPool.submit(new WashJob());
        Futures.addCallback(future1, new FutureCallback<Boolean>() {
            @Override
            public void onSuccess(@Nullable Boolean aBoolean) {
                job.cupOk = true;
                job.drinkTea();
            }

            @Override
            public void onFailure(Throwable throwable) {
                log.error("WashJob failed", throwable);
            }
        }, gPool);

        log.info("main end...");
    }

    @Slf4j
    public static class DrinkJob {
        volatile boolean waterOk = false;
        volatile boolean cupOk = false;

        public synchronized void drinkTea() {
            if (waterOk && cupOk) {
                log.info("drink tea");
            }
        }
    }

    public static class WashJob implements Callable<Boolean> {

        @Override
        public Boolean call() throws Exception {
            log.info("wash job...");
            GuavaAsync.parkS(2L);
            log.info("wash job end...");
            return true;
        }
    }

    public static class HotWaterJob implements Callable<Boolean> {

        @Override
        public Boolean call() throws Exception {
            log.info("HotWaterJob...");
            GuavaAsync.parkS(2L);
            log.info("HotWaterJob end...");
            return true;
        }
    }

}
